﻿using CPPEI.Coolzon.Common;
using CPPEI.Coolzon.Common.Startup;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CPPEI.App.Console
{
    /// <summary>
    /// 应用程序的父类，
    /// 父类中完成了，应用程序注册表信息的写入，以及对更新程序的调用,
    /// 当应用程序的启动参 /update no 时将不会启动更新程序
    /// <para>
    /// 参数的格式为 xx.exe /p1 p1value /p2 p2value /p3 ...
    /// </para>
    /// </summary>
    public abstract class XApplication
    {
        /// <summary>
        /// 获取当前AppDomain中的应用程序实例
        /// </summary>
        public static XApplication XCurrent
        {
            get
            {
                return null;// return Current as XApplication;
            }
        }

        public string Company { get; private set; }

        public string Product { get; private set; }

        /// <summary>
        /// 应用程序类型名称
        /// </summary>
        public string AppType { get; private set; }

        /// <summary>
        /// 应用程序的名称
        /// </summary>
        public string AppName { get; private set; }

        /// <summary>
        /// 更新程序的类型名称
        /// </summary>
        public string UpdateAppType { get; private set; }

        public Version Version { get; private set; }

        /// <summary>
        /// 应用程序信息
        /// </summary>
        public AppInfo AppInfo { get; private set; }

        /// <summary>
        /// 程序启动参数
        /// </summary>
        public StartupParamCollection StartupParams { get; private set; }

        /// <summary>
        /// 只有在构造函数里设置才有效果
        /// </summary>
        public XApplicationSettings Settings { get; private set; }
        System.Threading.Mutex _mutex;

        /// <summary>
        /// 构造应用程序,Company和Product信息将从Assembly信息中读取
        /// </summary>
        /// <param name="appType">应用程序类型</param>
        /// <param name="appName">应用程序名称</param>
        private XApplication(string appType, string appName)
        {
            System.Reflection.Assembly entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
            AssemblyProductAttribute productAttr = (AssemblyProductAttribute)Attribute.GetCustomAttribute(entryAssembly, typeof(AssemblyProductAttribute));
            AssemblyCompanyAttribute companyAttr = (AssemblyCompanyAttribute)Attribute.GetCustomAttribute(entryAssembly, typeof(AssemblyCompanyAttribute));

            this.Company = companyAttr.Company;
            this.Product = productAttr.Product;
            this.AppType = appType;
            this.AppName = appName;
            this.Version = entryAssembly.GetName().Version;
        }

        /// <summary>
        /// 构造应用程序，此程序不会启动更新程序
        /// </summary>
        /// <param name="company">公司名称</param>
        /// <param name="product">产品名称</param>
        /// <param name="appType">应用程序类型</param>
        /// <param name="appName">应用程序名称</param>
        public XApplication(string company, string product, string appType, string appName)
        {
            Company = company;
            Product = product;
            AppType = appType;
            AppName = appName;
            System.Reflection.Assembly entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
            this.Version = entryAssembly.GetName().Version;

            // 初始化程序设置
            Settings = new XApplicationSettings();
        }

        /// <summary>
        /// 构造应用程序,此程序需要启动更新程序
        /// </summary>
        /// <param name="company">公司名称</param>
        /// <param name="product">产品名称</param>
        /// <param name="appType">应用程序类型</param>
        /// <param name="appName">应用程序名称</param>
        /// <param name="appName">更新应用程序名称</param>
        public XApplication(string company, string product, string appType, string appName, string updateAppType)
            : this(company, product, appType, appName)
        {
            this.UpdateAppType = updateAppType;
        }

        /// <summary>
        /// true：继续运行，false：关闭
        /// </summary>
        /// <param name="args"></param>
        /// <returns>true：继续运行，false：关闭</returns>
        protected bool OnStartup(string[] args)
        {
            AppInfo = CoolzonRegistryUtil.GetAppInfo(this.Company, this.Product, this.AppType);
            if (AppInfo == null)
            {
                #region 写入注册表信息

                AppInfo = new CPPEI.Coolzon.Common.AppInfo();
                AppInfo.Company = this.Company;
                AppInfo.Product = this.Product;
                AppInfo.Type = AppType;
                AppInfo.Name = AppName;
                AppInfo.Directory = AppDomain.CurrentDomain.BaseDirectory;
                System.Reflection.Assembly entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
                AppInfo.AppFile = entryAssembly.Location;
                AppInfo.Version = entryAssembly.GetName().Version;

                Logger.Info("启动程序,{0}", AppInfo.ToString());
                CoolzonRegistryUtil.SaveAppInfo(this.Company, this.Product, AppInfo);

                #endregion
            }
            else
            {
                System.Reflection.Assembly entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
                Version curVersion = entryAssembly.GetName().Version;

                if (curVersion >= AppInfo.Version)
                {
                    AppInfo = new CPPEI.Coolzon.Common.AppInfo();
                    AppInfo.Company = this.Company;
                    AppInfo.Product = this.Product;
                    AppInfo.Type = AppType;
                    AppInfo.Name = AppName;
                    AppInfo.AppFile = entryAssembly.Location;
                    AppInfo.Version = curVersion;
                    AppInfo.Directory = AppDomain.CurrentDomain.BaseDirectory;

                    Logger.Info("启动程序,{0}", AppInfo.ToString());
                    CoolzonRegistryUtil.SaveAppInfo(this.Company, this.Product, AppInfo);
                }
                else
                {
                    Logger.Error("启动程序失败,程序版本低于已注册的版本信息,程序关闭,{0}", AppInfo.ToString());
                    
                    return false;
                }
            }

            #region 设置开机启动
            if (Settings.IsAutoRun)
            {
                StartupAppUtil.SetAutoRun(this.AppType, AppInfo.AppFile, true);
            }
            else
            {
                StartupAppUtil.SetAutoRun(this.AppType, AppInfo.AppFile, false);
            }
            #endregion

            #region 设置单例运行
            if (Settings.IsSingleton)
            {
                System.Reflection.Assembly entryAssembly = System.Reflection.Assembly.GetEntryAssembly();
                if (System.Threading.Mutex.TryOpenExisting(entryAssembly.FullName, out _mutex))
                {
                    // 已存在
                    return false;
                }
                else
                {
                    _mutex = new System.Threading.Mutex(true, entryAssembly.FullName);
                }
            }
            #endregion
           
            // 读取启动参数
            StartupParams = StartupUtil.Parse(args);

            /*
            if (false)
            {
                if (!string.IsNullOrEmpty(UpdateAppType))
                {
                    // 判断是否需要启动更新程序
                    if (StartupParams.GetValue("update") != "NO")
                    {
                        // 启动更新程序
                        // 检查更新
                        AppInfo updateAppInfo = Coolzon.Common.CoolzonRegistryUtil.GetAppInfo(this.Company, this.Product, this.UpdateAppType);
                        if (updateAppInfo != null)
                        {
                            StartupAppUtil.StartupApp(updateAppInfo, string.Format("/p {0}", AppInfo.Type));

                            // 关闭当前程序
                            return false;
                        }
                        else
                        {
                            Coolzon.Common.Logger.WarningToTag("WPF.Core", "获取更新程序:{0}出错,无法进行更新程序继续运行!", this.UpdateAppType);
                            return OnXStartup(StartupParams);
                        }
                    }
                    else
                    {
                        return OnXStartup(StartupParams);
                    }
                }
                else
                {
                    return OnXStartup(StartupParams);
                }
            }
            else
            {
                return OnXStartup(StartupParams);
            }*/
            return OnXStartup(StartupParams);
        }

        /// <summary>
        /// 初始化
        /// true：继续运行，false：关闭
        /// </summary>
        /// <param name="startupParams"></param>
        /// <returns>true：继续运行，false：关闭</returns>
        protected abstract bool OnXStartup(StartupParamCollection startupParams);

        /// <summary>
        /// 启动更新程序,并退出程序自身
        /// </summary>
        public void StartUpdateAppAndShutdown()
        {
            if (!string.IsNullOrEmpty(UpdateAppType))
            {
                // 启动更新程序
                // 检查更新
                AppInfo updateAppInfo = Coolzon.Common.CoolzonRegistryUtil.GetAppInfo(this.Company, this.Product, this.UpdateAppType);
                if (updateAppInfo != null)
                {
                    StartupAppUtil.StartupApp(updateAppInfo, string.Format("/p {0}", AppInfo.Type));

                    // 关闭当前程序
                }
                else
                {
                    Coolzon.Common.Logger.WarningToTag("WPF.Core", "获取更新程序:{0}出错,无法进行更新程序继续运行!", this.UpdateAppType);
                }
            }
            else
            {
                Coolzon.Common.Logger.WarningToTag("WPF.Core", "获取更新程序,没有定义更新程序的名称");
            }
        }

        /// <summary>
        /// 运行
        /// </summary>
        /// <param name="args">启动参数数组</param>
        public void Run(string[] args)
        {
            if (OnStartup(args))
            {
                Command.Run();
            }
        }
    }
}
